/**
 *
 */
package com.czmh.etc.onlinepubsys.services.impl;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.czmh.etc.onlinepubsys.entity.mingchuang.ApplyInfo;
import com.czmh.etc.onlinepubsys.entity.mingchuang.CurrentContext;
import com.czmh.etc.onlinepubsys.json.JsonResult;
import com.czmh.etc.onlinepubsys.maper.mingchuang.ApplyInfoMapper;
import com.czmh.etc.onlinepubsys.maper.mingchuang.CurrentContextMapper;
import com.czmh.etc.onlinepubsys.maper.mingchuang.MingchuangOrderMapper;
import com.czmh.etc.onlinepubsys.model.*;
import com.czmh.etc.onlinepubsys.utils.JsonResultUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import com.alibaba.fastjson.JSON;
import com.czmh.etc.common.core.utils.Sequence;
import com.czmh.etc.onlinepubsys.constants.GlobalStatusCode;
import com.czmh.etc.onlinepubsys.constants.WxFeeType;
import com.czmh.etc.onlinepubsys.dto.ApplyListDto;
import com.czmh.etc.onlinepubsys.dto.ApplyProgressDto;
import com.czmh.etc.onlinepubsys.dto.EtcAddressbookDto;
import com.czmh.etc.onlinepubsys.entity.WeiXinPayRefund;
import com.czmh.etc.onlinepubsys.entity.WeiXinPrePay;
import com.czmh.etc.onlinepubsys.entity.WxPrepayOrderInfo;
import com.czmh.etc.onlinepubsys.enums.PayWayEnum;
import com.czmh.etc.onlinepubsys.enums.WeiXinTradeTypeEnum;
import com.czmh.etc.onlinepubsys.enums.WeixinTradeStateEnum;
import com.czmh.etc.onlinepubsys.exceptions.EtcMsgException;
import com.czmh.etc.onlinepubsys.exceptions.ModelNotFoundException;
import com.czmh.etc.onlinepubsys.maper.EtcAddressbookMapper;
import com.czmh.etc.onlinepubsys.maper.EtcApplyMapper;
import com.czmh.etc.onlinepubsys.maper.EtcOrderMapper;
import com.czmh.etc.onlinepubsys.maper.EtcUserMapper;
import com.czmh.etc.onlinepubsys.maper.EtcWechatauthorizedMapper;
import com.czmh.etc.onlinepubsys.maper.EtcWechatrefundorderMapper;
import com.czmh.etc.onlinepubsys.maper.EtcWechatunifiedorderMapper;
import com.czmh.etc.onlinepubsys.request.DeliverETCEquipmentRequest;
import com.czmh.etc.onlinepubsys.response.WxPrePayResponse;
import com.czmh.etc.onlinepubsys.services.EtcOrderService;
import com.czmh.etc.onlinepubsys.utils.DatetimeUtil;
import com.czmh.etc.onlinepubsys.utils.PayUtil;
import com.czmh.etc.onlinepubsys.utils.WeiXinPayUtils;
import com.github.wxpay.sdk.WXPayUtil;
import org.springframework.util.CollectionUtils;

/**
 * @描述： @author： Seven.
 *
 * @创建日期：Jun 11, 2019 3:40:23 PM. @版本：1.0.0
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class EtcOrderSeviceImpl implements EtcOrderService {
    public Logger                       logger = LoggerFactory.getLogger(EtcOrderSeviceImpl.class);

    @Value("${wx.appid}")
    private String                      appid;
    @Value("${wx.wxPayMch_id}")
    private String                      mch_id;
    @Value("${wx.wxPayunifiedorderUrl}")
    private String                      payunifiedorderUrl;
    @Value("${wx.payRefundUrl}")
    private String                      payRefundUrl;
    @Value("${wx.wxPayAppSecret}")
    private String                      wxPayAppSecret;
    @Value("${wx.wxPayNotifyUrl}")
    private String                      wxPayNotifyUrl;
    @Value("${wx.wxPayRefundNotifyUrl}")
    private String                      wxPayRefundNotifyUrl;
    @Value("${wx.certpath}")
    private String                      certpath;
    @Value("${etc.obuCash}")
    private String                      obuCash;

    @Autowired
    private EtcUserMapper               etcUserMapper;
    @Autowired
    private EtcAddressbookMapper        etcAddressbookMapper;
    @Autowired
    private EtcOrderMapper              etcOrderMapper;
    @Autowired
    private EtcApplyMapper              etcApplyMapper;
    @Autowired
    private EtcWechatunifiedorderMapper etcWechatunifiedorderMapper;
    @Autowired
    private EtcWechatauthorizedMapper   etcWechatauthorizedMapper;
    @Autowired
    private EtcWechatrefundorderMapper  etcWechatrefundorderMapper;
    @Autowired
    private MingchuangOrderMapper mingchuangOrderMapper;
    @Autowired
    private CurrentContextMapper currentContextMapper;
    @Autowired
    private ApplyInfoMapper applyInfoMapper;


    @Override
    public Integer queryEtcPayState(String productSn, Integer payState) {
        QueryWrapper<com.czmh.etc.onlinepubsys.entity.mingchuang.EtcOrder> wrapper = new QueryWrapper<>();
        wrapper.eq("body", productSn);
        wrapper.eq("payState", payState);
        //wrapper.eq("pay_mode", 1);
        return mingchuangOrderMapper.selectCount(wrapper);
    }

    @Override
    public Integer queryEtcPayState(String productSn, Integer payState, Integer payMode) {
        QueryWrapper<com.czmh.etc.onlinepubsys.entity.mingchuang.EtcOrder> wrapper = new QueryWrapper<>();
        wrapper.eq("body", productSn);
        wrapper.eq("payState", payState);
        wrapper.eq("pay_mode", payMode);
        return mingchuangOrderMapper.selectCount(wrapper);
    }


    @Override
    public String submitaddrOrder(EtcAddressbookDto addr, String provinceCode) {
        EtcAddressbook useraddr = new EtcAddressbook(Sequence.getId());
        BeanUtils.copyProperties(addr, useraddr);
        etcAddressbookMapper.insert(useraddr);
        EtcOrder order = new EtcOrder(Sequence.getId());
        order.setUser_id(addr.getUser_id());
        order.setBody("设备押金");
        order.setDetail("设备押金");
        // 设置订单状态：0待发货 1已发货 2已收货
        order.setOrder_status(0);
        // 订单支付状态：0未支付，1已支付，2已退款
        order.setPay_status(0);
        Integer actualPayFee = new BigDecimal(obuCash).multiply(new BigDecimal("100")).intValue();
        order.setPaymoney(actualPayFee);
        order.setApply_id(addr.getApply_id());
        order.setCreate_time(new Date());
        order.setUpdate_time(new Date());
        order.setSh_address(addr.getAd_detailaddress());
        order.setSh_name(addr.getAd_consignee());
        order.setSh_phone(addr.getAd_consigneephone());
        etcOrderMapper.insert(order);
        EtcApply update = new EtcApply(addr.getApply_id());
        // 更新申请状态为填写银行卡
        if ("yue".equals(provinceCode)) {
            update.setApply_status(1);
        } else if("dian".equals(provinceCode)) {
            update.setApply_status(8);
        }
        etcApplyMapper.update(update);
        return order.getOrderid();
    }

    @Override
    public List<ApplyProgressDto> getApplyProgress(String order_id) {
        List<ApplyProgressDto> result = new ArrayList<ApplyProgressDto>();
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("orderid", order_id);
        List<EtcOrder> orders = etcOrderMapper.getAll(params);
        EtcOrder etcOrder = orders.get(0);
        params.put("user_id", etcOrder.getUser_id());
        List<EtcApply> etcApplies = etcApplyMapper.getAll(params);
        EtcApply etcApply = etcApplies.get(0);
        // 流程节点状态：1申请成功 2资料审核中 3设备制作中 4运输配送中 5已收货 6自助安装激活
        // 1.设置申请成功节点数据
        ApplyProgressDto applyPregress = new ApplyProgressDto();
        applyPregress.setProgressName(1);
        applyPregress.setStatus(1);
        result.add(applyPregress);
        // 2.设置资料审核中
        ApplyProgressDto zilPregress = new ApplyProgressDto();
        zilPregress.setProgressName(2);
        // 审核状态：0待审核，1审核通过，2审核不通过
        int applyStatus = etcApply.getApply_status();
        zilPregress.setStatus(applyStatus);
        result.add(zilPregress);
        /**
         * 如果审核通过则添加设备制作中节点
         */
        if (applyStatus == 1) {
            // 3.设置设备制作中
            ApplyProgressDto obucreatePregress = new ApplyProgressDto();
            obucreatePregress.setProgressName(3);
            obucreatePregress.setStatus(0);
            result.add(obucreatePregress);
            // 4.设置运输配送中节点
            ApplyProgressDto expressProgress = new ApplyProgressDto();
            expressProgress.setProgressName(4);
            List<String> detail = new ArrayList<String>();
            detail.add("收货人：" + etcOrder.getSh_name());
            detail.add("联系地址：" + etcOrder.getSh_address());
            detail.add("电话：" + etcOrder.getSh_phone());
            // 如果订单状态为已发货则设置运单号及流程状态为已发货
            if (1 == etcOrder.getOrder_status().intValue()) {
                expressProgress.setStatus(1);
                detail.add("配送单号：" + etcOrder.getExpressno());
            }
            result.add(expressProgress);
        }
        return result;
    }

    @Override
    public WxPrePayResponse preWxPayOrder(String order_id, String user_id, String spbill_create_ip) throws Exception {
        WxPrePayResponse data = new WxPrePayResponse();
        EtcOrder etcOrder = etcOrderMapper.getById(order_id);
        if (etcOrder == null) {
            throw new EtcMsgException("该订单不存在！");
        }
        Integer actualPayFee = etcOrder.getPaymoney();
        Date orderTime = new Date();
        String nonceStr = PayUtil.getNonceStr();
        WeiXinTradeTypeEnum jsapi = WeiXinTradeTypeEnum.JSAPI;
        Map<String, Object> wechatparams = new HashMap<String, Object>();
        wechatparams.put("user_id", user_id);
        List<EtcWechatauthorized> etcWechatauthorizedList = etcWechatauthorizedMapper.getAll(wechatparams);
        EtcWechatauthorized etcWechatauthorized = etcWechatauthorizedList.get(0);
        WeiXinPrePay weiXinPrePay = sealWeixinPerPay(appid, mch_id, etcOrder.getBody(), "", order_id, actualPayFee, orderTime, null, jsapi,
                "", etcWechatauthorized.getOpenid(), spbill_create_ip, nonceStr);
        String prePayXml = WeiXinPayUtils.getPrePayXml(weiXinPrePay, wxPayAppSecret);
        //调用微信支付的功能,获取微信支付code_url
        Map<String, Object> prePayRequest = WeiXinPayUtils.httpXmlRequest(payunifiedorderUrl, "POST", prePayXml);
        Object sign = prePayRequest.get("sign");
        Object return_msg = prePayRequest.get("return_msg");
        WxPrepayOrderInfo info = new WxPrepayOrderInfo();
        if (WeixinTradeStateEnum.SUCCESS.name().equals(prePayRequest.get("return_code")) && WeixinTradeStateEnum.SUCCESS.name().equals(prePayRequest.get("result_code"))) {
            // 验证签名
            String weiXinPrePaySign = WeiXinPayUtils.geWeiXintPrePaySign(appid, mch_id, weiXinPrePay.getDeviceInfo(), jsapi.name(), prePayRequest, wxPayAppSecret);
            if (sign != null && sign.toString().equals(weiXinPrePaySign)) {
                // 此处需要向微信订单表（etc_wechatunifiedorder）中插入一条记录
                EtcWechatunifiedorder wechatunifiedorder = new EtcWechatunifiedorder();
                wechatunifiedorder.setUser_id(user_id);
                wechatunifiedorder.setOut_trade_no(order_id);
                wechatunifiedorder.setAppid(appid);
                wechatunifiedorder.setMch_id(mch_id);
                wechatunifiedorder.setNonce_str(nonceStr);
                wechatunifiedorder.setSign(weiXinPrePay.getSign());
                wechatunifiedorder.setSign_type("MD5");
                wechatunifiedorder.setBody(etcOrder.getBody());
                wechatunifiedorder.setDetail(etcOrder.getDetail());
                wechatunifiedorder.setAttach("");
                wechatunifiedorder.setFee_type(WxFeeType.CNY);
                wechatunifiedorder.setTotal_fee(actualPayFee);
                wechatunifiedorder.setSpbill_create_ip(spbill_create_ip);
                wechatunifiedorder.setTime_start(DatetimeUtil.formatDate(orderTime, DatetimeUtil.DATETIME_PATTERN));
                wechatunifiedorder.setNotify_url(wxPayNotifyUrl);
                wechatunifiedorder.setTrade_type(jsapi.name());
                wechatunifiedorder.setReturn_code(prePayRequest.get("return_code").toString());
                if (return_msg != null) {
                    wechatunifiedorder.setReturn_msg(return_msg.toString());
                }
                wechatunifiedorder.setResult_code(prePayRequest.get("result_code").toString());
                wechatunifiedorder.setPrepay_id(prePayRequest.get("prepay_id").toString());
                wechatunifiedorder.setPaystatus(0);
                etcWechatunifiedorderMapper.insert(wechatunifiedorder);
                info.setAppId(appid);
                info.setPartnerid(mch_id);
                info.setPerpay_id(prePayRequest.get("prepay_id").toString());
                info.setNonce_str(PayUtil.getNonceStr());
                info.setTimestamp(Long.parseLong(String.valueOf(System.currentTimeMillis()).toString().substring(0, 10)));
                info.setTradeno(order_id);
                WeiXinPayUtils.getAppPaySign(info, wxPayAppSecret);
               //返回给APP端的参数，APP端再调起支付接口
                String page_prepay_id = prePayRequest.get("prepay_id").toString();
                Map<String, String> repData = new HashMap<>();
                //注意参数要区分大小写
                repData.put("appId", appid);
                repData.put("package", "prepay_id=" + page_prepay_id);
                //要添加签名方式
                repData.put("signType", "MD5");
                repData.put("nonceStr", WXPayUtil.generateNonceStr());
                repData.put("timeStamp", String.valueOf(System.currentTimeMillis() / 1000));
                //签名
                String paySign = WXPayUtil.generateSignature(repData, wxPayAppSecret);
                data.setAppId(appid);
                data.setPrepay_id(repData.get("package"));
                data.setNonceStr(repData.get("nonceStr"));
                data.setPaySign(paySign);
                data.setTimeStamp(repData.get("timeStamp"));
                logger.info("封装参数======"+ JSON.toJSONString(data));
            } else {
                // 此处需要保存错误订单信息
                // 此处需要向微信订单表（etc_wechatunifiedorder）中插入一条记录
                EtcWechatunifiedorder wechatunifiedorder = new EtcWechatunifiedorder();
                wechatunifiedorder.setUser_id(user_id);
                wechatunifiedorder.setOut_trade_no(order_id);
                wechatunifiedorder.setAppid(appid);
                wechatunifiedorder.setMch_id(mch_id);
                wechatunifiedorder.setNonce_str(nonceStr);
                if (StringUtils.isNotEmpty(weiXinPrePay.getSign())) {
                    wechatunifiedorder.setSign(weiXinPrePay.getSign());
                }
                wechatunifiedorder.setSign_type("MD5");
                wechatunifiedorder.setBody(etcOrder.getBody());
                wechatunifiedorder.setDetail(etcOrder.getDetail());
                wechatunifiedorder.setAttach("");
                wechatunifiedorder.setFee_type(WxFeeType.CNY);
                wechatunifiedorder.setTotal_fee(actualPayFee);
                wechatunifiedorder.setSpbill_create_ip(spbill_create_ip);
                wechatunifiedorder.setTime_start(DatetimeUtil.formatDate(orderTime, DatetimeUtil.DATETIME_PATTERN));
                wechatunifiedorder.setNotify_url(wxPayNotifyUrl);
                wechatunifiedorder.setTrade_type(jsapi.name());
                wechatunifiedorder.setReturn_code(prePayRequest.get("return_code").toString());
                if (return_msg != null) {
                    wechatunifiedorder.setReturn_msg(return_msg.toString());
                }
                wechatunifiedorder.setResult_code(prePayRequest.get("result_code").toString());
                // 以下两个异常时保存
                wechatunifiedorder.setErr_code(prePayRequest.get("err_code").toString());
                wechatunifiedorder.setErr_code_des(prePayRequest.get("err_code_des").toString());
                wechatunifiedorder.setPaystatus(0);
                etcWechatunifiedorderMapper.insert(wechatunifiedorder);
                throw new Exception("微信返回结果签名异常");
            }
        } else {
            // 此处需要向微信订单表（m_wechatunifiedorder）中插入一条记录
            EtcWechatunifiedorder wechatunifiedorder = new EtcWechatunifiedorder();
            wechatunifiedorder.setUser_id(user_id);
            wechatunifiedorder.setOut_trade_no(order_id);
            wechatunifiedorder.setAppid(appid);
            wechatunifiedorder.setMch_id(mch_id);
            wechatunifiedorder.setNonce_str(nonceStr);
            if (StringUtils.isNotEmpty(weiXinPrePay.getSign())) {
                wechatunifiedorder.setSign(weiXinPrePay.getSign());
            }
            wechatunifiedorder.setSign_type("MD5");
            wechatunifiedorder.setBody(etcOrder.getBody());
            wechatunifiedorder.setDetail(etcOrder.getDetail());
            wechatunifiedorder.setAttach("");
            wechatunifiedorder.setFee_type(WxFeeType.CNY);
            wechatunifiedorder.setTotal_fee(actualPayFee);
            wechatunifiedorder.setSpbill_create_ip(spbill_create_ip);
            wechatunifiedorder.setTime_start(DatetimeUtil.formatDate(orderTime, DatetimeUtil.DATETIME_PATTERN));
            wechatunifiedorder.setNotify_url(wxPayNotifyUrl);
            wechatunifiedorder.setTrade_type(jsapi.name());
            wechatunifiedorder.setReturn_code(prePayRequest.get("return_code").toString());
            if (return_msg != null) {
                wechatunifiedorder.setReturn_msg(return_msg.toString());
            }
            wechatunifiedorder.setResult_code(prePayRequest.get("result_code").toString());
            // 以下两个异常时保存
            wechatunifiedorder.setErr_code(prePayRequest.get("err_code").toString());
            wechatunifiedorder.setErr_code_des(prePayRequest.get("err_code_des").toString());
            wechatunifiedorder.setPaystatus(0);
            etcWechatunifiedorderMapper.insert(wechatunifiedorder);
            // 此处需要保存错误订单信息
            throw new Exception("请求微信异常");
        }
        return data;
    }

    @Override
    public void confirmgoods(String order_id) {
        EtcOrder etcOrder = new EtcOrder(order_id);
        // 更新订单状态为已收货：2
        etcOrder.setOrder_status(2);
        etcOrderMapper.update(etcOrder);
    }

    @Override
    public List<ApplyListDto> applylist(String user_id) {
        List<ApplyListDto> applyListDtos = etcOrderMapper.getApplyOrderList(user_id);
        return applyListDtos;
    }

    @Override
    public Boolean verifyNotify(String payWayCode, Map<String, String> notifyMap) throws Exception {
        String out_trade_no = notifyMap.get("out_trade_no");
        // 根据银行订单号获取支付信息
        if (PayWayEnum.WEIXIN.name().equals(payWayCode)) {
            logger.info("微信订单号{}", out_trade_no);

            EtcWechatunifiedorder wechatunifiedorder = etcWechatunifiedorderMapper.getById(out_trade_no);
            if (wechatunifiedorder == null) {
                throw new Exception("非法微信支付订单,订单不存在");
            }

            Integer total_fee = 0;
            String wx_total_fee = notifyMap.get("total_fee");
            if (StringUtils.isNotEmpty(wx_total_fee)) {
                total_fee = Integer.valueOf(wx_total_fee);
            }

            if (!wechatunifiedorder.getTotal_fee().equals(total_fee)) {
                throw new Exception("非法微信支付订单,订单金额不对！");
            }

            String sign = notifyMap.remove("sign");
            // 根据配置信息验证签名
            if (WeiXinPayUtils.notifySign(notifyMap, sign, wxPayAppSecret)) {
                return true;
            } else {
                throw new Exception("微信签名失败");
            }
        } else {
            return false;
        }
        // else if (PayWayEnum.ALIPAY.name().equals(payWayCode)) {
        // LOG.info("支付宝订单号{}",out_trade_no);
        //
        // Malipayunifiedorder alipayunifiedorder =
        // malipayunifiedorderMapper.getById(out_trade_no);
        // if(alipayunifiedorder == null)
        // throw new Exception("非法支付宝支付订单,订单不存在");
        //
        // Double totalAmount = 0.00;
        // String total_amount = notifyMap.get("total_amount");
        // if(StringUtils.isNotEmpty(total_amount))
        // totalAmount = Double.valueOf(total_amount);
        //
        // if(!Double.valueOf(alipayunifiedorder.getTotal_amount()).equals(totalAmount))
        // throw new Exception("非法支付宝支付订单,订单金额不对！");
        //
        // boolean rsaCheckV1 = AlipaySignature.rsaCheckV1(notifyMap,
        // ALIPAY_PUBLIC_KEY, ALIPAY_CHARSET, SIGN_TYPE);
        // if(rsaCheckV1){
        // //验证成功
        // return true;
        // }else{
        // //验证失败
        // throw new Exception("支付宝签名异常");
        // }
        // } else {
        // throw new Exception("错误的支付方式");

        // }
    }

    @Override
    public void dealPaymentNotifySuccess(String payWayCode, Map<String, String> notifyMap) {
        String out_trade_no = notifyMap.get("out_trade_no");
        String transaction_id = notifyMap.get("transaction_id");
        // 根据银行订单号获取支付信息
        if (PayWayEnum.WEIXIN.name().equals(payWayCode)) {
            logger.info("商户订单号{}", out_trade_no);
//            EtcOrder etcOrder = etcOrderMapper.getById(out_trade_no);
            EtcOrder update = new EtcOrder(out_trade_no);
            update.setTransaction_id(transaction_id);
            update.setPay_status(1);
            update.setOrder_status(0);
            update.setUpdate_time(new Date());
            etcOrderMapper.update(update);
            logger.info("微信订单号{}", transaction_id);
        }
    }

    @Transactional
    @Override
    public void approveETCApply(String applyID, boolean passed, String rejectMSG, Integer approvedUserID) {
        if (applyID == null || applyID.trim().length() <= 0) {
            throw new NullPointerException("传入的applyID不能为空！");
        }
        if (approvedUserID == null) {
            throw new NullPointerException("传入的approvedUserID不能为空！");
        }

        EtcApply apply = etcApplyMapper.getById(applyID);
        if (apply != null) {
            if (passed == true) {
                // 审批通过
                apply.setApply_status(1);
            } else {
                // 审批不通过
                apply.setApply_status(2);
                apply.setApply_refusereason(rejectMSG);
            }

            apply.setApply_approve_time(new Date());
            apply.setApply_approve_userid(approvedUserID);

            etcApplyMapper.update(apply);
        } else {
            throw new ModelNotFoundException(GlobalStatusCode.FAILED, "没有找到对应的EtcApply对象！");
        }
    }

    @Override
    public void deliverETCEquipment(DeliverETCEquipmentRequest.DeliverETCDetail detail, Integer deliverUserId,
            Date deliverTime) {
        Assert.notNull(detail, "传入发货明细不能为空！");
        Assert.notNull(deliverUserId, "传入审批人UserId不能为空！");
        Assert.notNull(deliverTime, "传入的发货时间不能为空！");

        EtcOrder order = etcOrderMapper.getById(detail.getOrderId());
        if (order != null) {
            order.setDeliver_time(deliverTime);
            order.setDeliver_userid(deliverUserId);
            order.setExpressno(detail.getExpressNo());
            order.setOrder_status(1);

            etcOrderMapper.update(order);
        } else {
            throw new ModelNotFoundException(GlobalStatusCode.FAILED, "没有找到对应的EtcOrder对象！");
        }
    }

    /**
     * 封装预支付实体
     *
     * @param appId
     *            公众号ID
     * @param mchId
     *            商户号
     * @param productName
     *            商品描述
     * @param remark
     *            支付备注
     * @param out_trade_no
     *            银行订单号
     * @param totalFee
     *            订单价格
     * @param orderTime
     *            订单下单时间
     * @param orderPeriod
     *            订单有效期
     * @param weiXinTradeTypeEnum
     *            微信支付方式
     * @param productId
     *            商品ID
     * @param openId
     *            用户标识
     * @param orderIp
     *            下单IP
     * @return
     */
    private WeiXinPrePay sealWeixinPerPay(String appId, String mchId, String productName, String remark,
            String out_trade_no, Integer totalFee, Date orderTime, Integer orderPeriod,
            WeiXinTradeTypeEnum weiXinTradeTypeEnum, String productId, String openId, String orderIp, String nonceStr) {
        WeiXinPrePay weiXinPrePay = new WeiXinPrePay();
        weiXinPrePay.setAppid(appId);
        weiXinPrePay.setAttach(remark);
        weiXinPrePay.setBody(productName);
        weiXinPrePay.setMchId(mchId);
        weiXinPrePay.setNonceStr(nonceStr);
        weiXinPrePay.setNotifyUrl(wxPayNotifyUrl);
        weiXinPrePay.setOutTradeNo(out_trade_no);
        weiXinPrePay.setSpbillCreateIp(orderIp);
        weiXinPrePay.setTotalFee(totalFee);
        weiXinPrePay.setTradeType(weiXinTradeTypeEnum);
        weiXinPrePay.setFeeType(WxFeeType.CNY);
        weiXinPrePay.setTimeStart(DatetimeUtil.formatDate(orderTime, DatetimeUtil.DATETIME_PATTERN));
        weiXinPrePay.setOpenid(openId);
        return weiXinPrePay;
    }

    @Override
    public JsonResult refundWxPayOrder(String orderNo, String userId) throws Exception {
        com.czmh.etc.onlinepubsys.entity.mingchuang.EtcOrder etcOrder = new com.czmh.etc.onlinepubsys.entity.mingchuang.EtcOrder();
        Map<String, Object> params = new HashMap<String, Object>(0);
        params.put("orderNo", orderNo);
        List<com.czmh.etc.onlinepubsys.entity.mingchuang.EtcOrder> etcOrders = mingchuangOrderMapper.selectByMap(params);
        if(!CollectionUtils.isEmpty(etcOrders)){
            etcOrder = etcOrders.get(0);
        }
        if (etcOrder == null) {
            throw new EtcMsgException("该订单不存在！");
        }
        //检查订单是否激活
        QueryWrapper<ApplyInfo> queryWrapper = new QueryWrapper();
        queryWrapper.eq("orderNo", orderNo);
        ApplyInfo applyInfo = applyInfoMapper.selectOne(queryWrapper);
        if(applyInfo != null && applyInfo.getState() == 2){
            return JsonResultUtil.toErrorResult("退款申请失败，设备已激活！");
        }
        Integer payRefundFee = etcOrder.getAmount();
        WeiXinPayRefund weiXinPayRefund = new WeiXinPayRefund();
        weiXinPayRefund.setAppid(appid);
        weiXinPayRefund.setMchId(mch_id);
        weiXinPayRefund.setNotifyUrl(wxPayRefundNotifyUrl);
        weiXinPayRefund.setOutRefundNo(orderNo);
        weiXinPayRefund.setOutTradeNo(orderNo);
        weiXinPayRefund.setRefundFee(payRefundFee);
        weiXinPayRefund.setTotalFee(payRefundFee);
        String data = WeiXinPayUtils.getPayRefundXml(weiXinPayRefund, wxPayAppSecret);
        // 调用微信支付的功能,获取微信支付code_url
        String xmlStr = WeiXinPayUtils.doRefund(payRefundUrl, data, mch_id, certpath);
        logger.info("返回的xml信息：" + xmlStr);
        Map<String, Object> payRefundResponse = com.czmh.etc.onlinepubsys.utils.mingchuang.PayUtil.getMapFromXML(xmlStr);
        logger.info("返回的map信息：" + JSON.toJSONString(payRefundResponse));
        // 保存退款申请记录
        if(WeixinTradeStateEnum.SUCCESS.name().equals(payRefundResponse.get("return_code")) && WeixinTradeStateEnum.SUCCESS.name().equals(payRefundResponse.get("result_code"))){
            // 保存退款申请记录
            EtcWechatrefundorder etcWechatrefundorder = JSON.parseObject(JSON.toJSONString(payRefundResponse), EtcWechatrefundorder.class);
            try {
                EtcWechatrefundorder etcWechatrefundorder1 = etcWechatrefundorderMapper.getById(etcWechatrefundorder.getRefund_id());
                if(etcWechatrefundorder1 == null){
                    //微信退款成功之后更新mingchuang_order状态为3
                    QueryWrapper<com.czmh.etc.onlinepubsys.entity.mingchuang.EtcOrder> wrapper = new QueryWrapper<>();
                    wrapper.eq("orderNo", orderNo);
                    com.czmh.etc.onlinepubsys.entity.mingchuang.EtcOrder order = mingchuangOrderMapper.selectOne(wrapper);
                    if (null != order){
                        mingchuangOrderMapper.updateByOrderNo(order.getOrderNo(), order.getPayNo(), 3);
                        logger.info("微信退款成功之后更新mingchuang_order状态为3已退款：" + JSON.toJSONString(order));
                    }else{
                        logger.info("微信退款成功之后更新mingchuang_order状态为3已退款：" + "记录为NULL");
                    }
                    //微信退款成功之后更新用户流程为0
                    QueryWrapper<CurrentContext> currentContextQueryWrapper = new QueryWrapper<>();
                    currentContextQueryWrapper.eq("orderNo", orderNo);
                    currentContextQueryWrapper.eq("delete_flag", 0);
                    CurrentContext ctx = currentContextMapper.selectOne(currentContextQueryWrapper);
                    if (ctx != null) {
                        ctx.setState(0);
                        currentContextMapper.updateById(ctx);
                        logger.info("微信退款成功之后更新mingchuang_currentContext状态为0：" + JSON.toJSONString(ctx));
                    }else{
                        logger.info("微信退款成功之后更新mingchuang_currentContext状态为0：" + "记录为NULL");
                    }
                    //保存退款申请记录
                    etcWechatrefundorderMapper.insert(etcWechatrefundorder);
                }else {
                    return JsonResultUtil.toResult("您已退款申请成功！");
                }
            }catch (Exception e){
                e.printStackTrace();
                logger.info("保存退款申请记录失败：" + JSON.toJSONString(etcWechatrefundorder));
            }
            return JsonResultUtil.toResult("退款申请成功！");
        }
        return JsonResultUtil.toErrorResult("退款申请失败，请联系管理员！");
    }

    @Override
    public void updateOrderRefund(String out_trade_no) {
        EtcOrder etcOrder = etcOrderMapper.getById(out_trade_no);
        if (etcOrder == null) {
            throw new EtcMsgException("该订单不存在！");
        }
        EtcOrder update = new EtcOrder(out_trade_no);
        update.setPay_status(2);
        etcOrderMapper.update(update);
        logger.info("更新退款状态成功，订单号：" + out_trade_no);
    }

    /**
     * 根据订单号查询订单状态和设备状态
     * @param orderNo 订单号
     * @return
     */
    @Override
    public com.czmh.etc.onlinepubsys.entity.mingchuang.EtcOrder queryByOrderNo(String orderNo) {
        QueryWrapper<com.czmh.etc.onlinepubsys.entity.mingchuang.EtcOrder> wrapper = new QueryWrapper<>();
        wrapper.eq("orderNo", orderNo);
        return mingchuangOrderMapper.selectOne(wrapper);
    }

    /**
     * 根据产品编码查询产品是否存在
     * @param productSn 订单号
     * @return
     */
    @Override
    public int isExistProductSn(String productSn) {
        Map<String, Object> queryMap = new HashMap<>();
        queryMap.put("deleteFlag", "0");
        queryMap.put("productSn", productSn);
        int count = etcOrderMapper.isExistObu(queryMap);
        return count;
    }

    /**
     * 根据根据产品编号查询产品是否被支付
     * @param productSn 产品编号
     * @return
     */
    @Override
    public Integer queryByProductSn(String productSn, Integer payState) {
        QueryWrapper<com.czmh.etc.onlinepubsys.entity.mingchuang.EtcOrder> wrapper = new QueryWrapper<>();
        wrapper.eq("body", productSn);
        wrapper.eq("payState", payState);
        wrapper.eq("pay_mode", 1);
        return mingchuangOrderMapper.selectCount(wrapper);
    }

    /**
     * 根据根据产品编号查询产品是否被支付
     * @param productSn 产品编号
     * @return
     */
    @Override
    public Integer queryByProductSn(String productSn, Integer payState, Integer payMode) {
        QueryWrapper<com.czmh.etc.onlinepubsys.entity.mingchuang.EtcOrder> wrapper = new QueryWrapper<>();
        wrapper.eq("body", productSn);
        wrapper.eq("payState", payState);
        wrapper.eq("pay_mode", payMode);
        return mingchuangOrderMapper.selectCount(wrapper);
    }

    @Override
    public EtcDevice queryObject(Map<String, Object> queryMap) {
        queryMap.put("offset", 0);
        queryMap.put("limit", 1);
        List<EtcDevice> list = etcOrderMapper.queryObjects(queryMap);
        if(!CollectionUtils.isEmpty(list)){
            return list.get(0);
        }
        return null;
    }

    @Override
    public int updateObject(EtcDevice etcDevice) {
        return etcOrderMapper.updateObject(etcDevice);
    }

    @Override
    public int updateById(com.czmh.etc.onlinepubsys.entity.mingchuang.EtcOrder etcOrder) {
        return mingchuangOrderMapper.updateById(etcOrder);
    }

    @Override
    public int deleteById(com.czmh.etc.onlinepubsys.entity.mingchuang.EtcOrder etcOrder) {
        return mingchuangOrderMapper.deleteById(etcOrder.getId());
    }
}
